var express = require('express');
var router = express.Router();
const nearAPI = require('near-api-js');
const sha256 = require('js-sha256');
const getConfig = require('./config');
const {formatAmount} = require('./utils');

/**
 * 交易签名
 */
router.post('/sendTransaction', function (req, res) {
    const params = req.body;
    sendTransaction(params.sender, params.receiver, params.amount, params.privateKey,params.blockHash,params.nonce).then((tx) => {
        res.set('Content-Type', 'application/json');
        res.status(200).send('{\"result\":\"' + tx + '\"}');
    });
});

/**
 * 异步签名
 *
 * @param sender 发送者
 * @param receiver 接受者
 * @param amount 金额
 * @param privateKey    私钥种子
 * @param blockHash    最新区块hash
 * @param nonce 发送随机数+1后的
 * @returns {Promise<Transaction>}
 */
async function sendTransaction(sender, receiver, amount, privateKey,blockHash,nonce) {
    try {

        const keyPair = nearAPI.utils.key_pair.KeyPairEd25519.fromString(privateKey);
        const publicKey = keyPair.getPublicKey();
        // get sender access info
        const accessKey = await api.query(
            `access_key/${sender}/${publicKey.toString()}`,
            ""
        );
        nonce = ++accessKey.nonce;
        const actions = [nearAPI.transactions.transfer(formatAmount(amount))];
        const recentBlockHash = nearAPI.utils.serialize.base_decode(accessKey.block_hash);
        // create transaction
        const transaction = nearAPI.transactions.createTransaction(
            sender,
            publicKey,
            receiver,
            nonce,
            actions,
            recentBlockHash
        );
        // before we can sign the transaction we must perform three steps...
        // 1) serialize the transaction in Borsh
        const serializedTx = nearAPI.utils.serialize.serialize(
            nearAPI.transactions.SCHEMA,
            transaction
        );
        // 2) hash the serialized transaction using sha256
        const serializedTxHash = new Uint8Array(sha256.sha256.array(serializedTx));
        // 3) create a signature using the hashed transaction
        const signature = keyPair.sign(serializedTxHash);
        // now we can sign the transaction :)
        const signedTransaction = new nearAPI.transactions.SignedTransaction({
            transaction,
            signature: new nearAPI.transactions.Signature({
                keyType: transaction.publicKey.keyType,
                data: signature.signature
            })
        });
        // encodes signed transaction to serialized Borsh (required for all transactions)
        const serializedTxEncode = signedTransaction.encode();
        const result = await api.sendJsonRpc(
            'broadcast_tx_commit',
            [Buffer.from(serializedTxEncode).toString('base64')]
        );
        // console results :)
        console.log('Results: ', result);
        console.log('Transaction Results: ', result.transaction);
        console.log('--------------------------------------------------------------------------------------------')
        console.log('OPEN LINK BELOW to see transaction in NEAR Explorer!');
        console.log(`transactions/${result.transaction.hash}`);
        console.log('--------------------------------------------------------------------------------------------');
        return result.transaction.hash;
    } catch (error) {
        console.log(error);
        return "";
    }
}

var api;

async function getApi() {

    // Create the API and wait until ready
    if (api === undefined) {
        console.log('Create the API and wait until ready');
        console.log('Initialise the provider to connect to the local node');
        const config = getConfig('testnet');
        api = new nearAPI.providers.JsonRpcProvider(config.nodeUrl);

        console.log(`cusccess`);
    }
    return api;
}

getApi();

module.exports = router;
